<template>
  <div class="container">
    <canvas canvas-id="canvas"
    @touchstart="touchstart" 
    @touchmove="touchmove" 
    @touchend="touchend"
    :style="{width: width+'px',height: height+'px'}"
    />
  </div>
</template>

<script>
/* eslint-disable no-unused-vars */
/* eslint-disable standard/no-callback-literal */
/* eslint-disable camelcase */
/* eslint-disable no-undef */
let lastFrameTime = 0;
function InterpolateAndDrawBeizers(points, bClosedCurve, smoothValue, ctx) {
    let size = points.length;
    if (size < 3) {
        return;
    }

    // if is close curve then add the first point at the end
    if (bClosedCurve) {
        points.push(points[0]);
    }

    // iterate for points but the last one
    for (let i = 0; i < size - 1; i++) {
        // Assume we need to calculate the control
        // points between (x1,y1) and (x2,y2).
        // Then x0,y0 - the previous vertex,
        //      x3,y3 - the next one.
        let x1 = points[i].x;
        let y1 = points[i].y;

        let x2 = points[i + 1].x;
        let y2 = points[i + 1].y;

        let x0 = 0.0;
        let y0 = 0.0;

        let previousPoint = null;
        if (i === 0) {
            // if is first point
            if (bClosedCurve) {
                previousPoint = points[size - 2];// last Point, but one (due inserted the first at the end)
                x0 = previousPoint.x;
                y0 = previousPoint.y;
            } else {
                // Get some previouse point
                previousPoint = points[i]; // if is the first point the previous one will be it self
                x0 = previousPoint.x;
                y0 = previousPoint.y;
            }
        } else {
            x0 = points[i - 1].x; // Previous Point
            y0 = points[i - 1].y;
        }

        let x3 = 0.0;
        let y3 = 0.0;
        let nextPoint = null;
        if (i === size - 2) {
            // if is the last point
            if (bClosedCurve) {
                nextPoint = points[1]; // second Point(due inserted the first at the end)
                x3 = nextPoint.x;
                y3 = nextPoint.y;
            } else {
                // Get some next point
                nextPoint = points[i + 1]; // if is the last point the next point will be the last one
                x3 = nextPoint.x;
                y3 = nextPoint.y;
            }
        } else {
            x3 = points[i + 2].x; // Next Point
            y3 = points[i + 2].y;
        }

        let xc1 = (x0 + x1) * 0.5;
        let yc1 = (y0 + y1) * 0.5;
        let xc2 = (x1 + x2) * 0.5;
        let yc2 = (y1 + y2) * 0.5;
        let xc3 = (x2 + x3) * 0.5;
        let yc3 = (y2 + y3) * 0.5;
        let len1 = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        let len2 = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
        let len3 = Math.sqrt((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2));

        let k1 = len1 / (len1 + len2);
        let k2 = len2 / (len2 + len3);

        let xm1 = xc1 + (xc2 - xc1) * k1;
        let ym1 = yc1 + (yc2 - yc1) * k1;
        let xm2 = xc2 + (xc3 - xc2) * k2;
        let ym2 = yc2 + (yc3 - yc2) * k2;
        // Resulting control points. Here smooth_value is mentioned
        // above coefficient K whose value should be in range [0...1].
        let ctrl1_x = xm1 + (xc2 - xm1) * smoothValue + x1 - xm1;
        let ctrl1_y = ym1 + (yc2 - ym1) * smoothValue + y1 - ym1;
        let ctrl2_x = xm2 + (xc2 - xm2) * smoothValue + x2 - xm2;
        let ctrl2_y = ym2 + (yc2 - ym2) * smoothValue + y2 - ym2;

        let startPoint = {x: x1, y: y1};
        let endPoint = {x: x2, y: y2};

        let firstControlPoint = i === 0 && !bClosedCurve ? {x: x1, y: y1} : {x: ctrl1_x, y: ctrl1_y};
        let secondControlPoint = i === points.length - 2 && !bClosedCurve ? {x: x2, y: y2} : {x: ctrl2_x, y: ctrl2_y};
        ctx.beginPath();
        ctx.moveTo(startPoint.x, startPoint.y);
        ctx.bezierCurveTo(firstControlPoint.x, firstControlPoint.y, secondControlPoint.x, secondControlPoint.y, endPoint.x, endPoint.y);
        ctx.stroke();
    }
}

function isInCircle(p1, p2, o, r) {
    // https://blog.csdn.net/swordsman___ddz/article/details/52659060
    let r1 = Math.sqrt(Math.pow(p1.x - o.x, 2) + Math.pow(p1.y - o.y, 2));
    let r2 = Math.sqrt(Math.pow(p2.x - o.x, 2) + Math.pow(p2.y - o.y, 2));
    if (r1 < r && r2 < r) {
        return false;
    } else if ((r1 < r && r2 >= r) || (r1 >= r && r2 < r)) {
        return true;
    } else {
        let a = null;
        let b = null;
        let c = null;
        let dist1 = null;
        let dist2 = null;
        let angle1 = null;
        let angle2 = null; // ax + by + c = 0;
        if (p1.x === p2.x) {
            a = 1;
            b = 0;
            c = -p1.x; // 特殊情况判断，分母不能为零
        } else if (p1.y === p2.y) {
            a = 0;
            b = 1;
            c = -p1.y; // 特殊情况判断，分母不能为零
        } else {
            a = p1.y - p2.y;
            b = p2.x - p1.x;
            c = p1.x * p2.y - p1.y * p2.x;
        }
        dist1 = a * o.x + b * o.y + c;
        dist1 *= dist1;
        dist2 = (a * a + b * b) * r * r;
        if (dist1 > dist2) {
            return false;
        }// 点到直线距离大于半径r
        angle1 = (o.x - p1.x) * (p2.x - p1.x) + (o.y - p1.y) * (p2.y - p1.y);
        angle2 = (o.x - p2.x) * (p1.x - p2.x) + (o.y - p2.y) * (p1.y - p2.y);
        if (angle1 > 0 && angle2 > 0) {
            return true;
        }// 余弦都为正，则是锐角
    }
    return false;
}

let canvas = {
    width: 0,
    height: 0
};

export default {
    data() {
        return {
            width: 0,
            height: 0,
            radius: 100,
            touching: false,
            lines: [],
            lastPoint: null
        };
    },
    methods: {
        touchstart(e) {
            this.lines.push({
                points: [{
                    x: e.x,
                    y: e.y
                }]
            });
            this.ctx.beginPath();
            this.ctx.setStrokeStyle('orange');
            this.touching = true;
        },
        touchmove(e) {
            let {x, y} = e;
            let points = this.lines.slice(-1)[0].points;
            if (this.touching) {
                let lastPoint = points.slice(-1)[0];
                points.push({x, y});
                this.ctx.moveTo(lastPoint.x, lastPoint.y);
                this.ctx.lineTo(x, y);
                this.ctx.stroke();
                this.ctx.draw(true);
            }
        },
        touchend(e) {
            this.touching = false;
            let ctx = this.ctx;
            let counter = 0;
            let r = {
                x: canvas.width / 2,
                y: canvas.height / 2
            };
            let crossPoints = [];

            this.lines.slice(-1)[0].points.forEach((p, index, points) => {
                if (index === points.length - 1) {
                    return;
                }

                let nextP = points[index + 1];
                if (isInCircle(p, nextP, r, this.radius)) {
                    crossPoints.push({
                        x: (p.x + nextP.x) / 2,
                        y: (p.y + nextP.y) / 2,
                        start: p,
                        end: nextP
                    });
                    counter++;
                }
            });

            if (counter !== 2) {
                wx.showToast({
                    title: '本次操作无效，切割线必须与边缘相交两次，请重新切割',
                    duration: 2000,
                    icon: 'none'
                });
                this.lines.pop();
                this.redraw();
            } else {
                let line = this.lines.pop();
                let pStart = crossPoints[0];
                let pEnd = crossPoints[1];
                let pos1 = line.points.indexOf(crossPoints[0].start);
                let pos2 = line.points.indexOf(crossPoints[1].start);

                let realLine = [{
                    x: pStart.x,
                    y: pStart.y
                }];
                for (let i = pos1; i <= pos2; i++) {
                    realLine.push({
                        x: line.points[i].x,
                        y: line.points[i].y
                    });
                }
                realLine.push({
                    x: pEnd.x,
                    y: pEnd.y
                });
                this.lines.push({points: realLine});
                this.drawCircle();
                this.drawLines();
                ctx.draw();
            }

            // this.ctx.clearRect(0, 0, canvas.width, canvas.height);
            // this.ctx.draw();
            // this.ctx.setStrokeStyle('blue');
            // InterpolateAndDrawBeizers(this.points, false, 0.6, this.ctx);
            // this.ctx.draw(true);
        },
        redraw() {
            this.drawCircle();
            this.drawLines();
            this.ctx.draw();
        },
        drawCircle() {
            let ctx = this.ctx;
            ctx.beginPath();
            ctx.rect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'skyblue';
            ctx.fill();
            ctx.beginPath();
            ctx.arc(canvas.width / 2, canvas.height / 2, this.radius, 0, Math.PI * 2);
            ctx.fillStyle = '#A9D18E';
            ctx.fill();
        },
        drawLines() {
            this.lines.forEach(l => {
                this.drawPoints(l.points);
            });
        },
        drawPoints(points) {
            let ctx = this.ctx;
            ctx.beginPath();
            ctx.setStrokeStyle('orange');
            points.forEach((p, index) => {
                if (index !== points.length - 1) {
                    let nextP = points[index + 1];
                    this.ctx.moveTo(p.x, p.y);
                    this.ctx.lineTo(nextP.x, nextP.y);
                    this.ctx.stroke();
                }
            });
        },
        clear() {
            this.lines = [];
            this.drawCircle();
            this.ctx.draw();
        }
    },
    onReady() {
        wx.getSystemInfo({
            // 获取系统信息成功，将系统窗口的宽高赋给页面的宽高
            success: res => {
                this.width = canvas.width = res.windowWidth;
                // console.log(that.width)   375
                this.height = canvas.height = res.windowHeight - 100;
                // console.log(that.height)  625
                // 这里的单位是PX，实际的手机屏幕有一个Dpr，这里选择iphone，默认Dpr是2
                this.ctx = wx.createCanvasContext('canvas');
                this.drawCircle();
                this.ctx.draw();
            }
        });
    }
};
</script>

<style lang="scss" scoped>
.container{
  height: 80vh;
  width: 100vw;
  canvas {
  }
}
</style>